#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
数据库图形界面客户端
================

基于tkinter的数据库管理工具，类似于MySQL Workbench的简化版本
支持SQL查询、表浏览、数据编辑等功能
"""

import tkinter as tk
from tkinter import ttk, messagebox, filedialog, scrolledtext, simpledialog
import sys
import os
from datetime import datetime
import threading
import queue
import re

# 添加路径以导入SQL编译器和执行引擎
current_dir = os.path.dirname(os.path.abspath(__file__))
root_dir = os.path.dirname(os.path.dirname(current_dir))
sys.path.insert(0, root_dir)
sys.path.insert(0, os.path.join(root_dir, 'SqlCompiler'))

try:
    from LexicalAnalysis import LexicalAnalyzer
    from SyntaxAnalysis import SyntaxAnalyzer
    from SemanticAnalysis import SemanticAnalyzer
    from logical_plan_generator import LogicalPlanGenerator
    from physical_plan_optimizer import PhysicalPlanOptimizer
    from ExecutionEngine.executor import QueryExecutor
    from ExecutionEngine.storage_adapter import StorageEngineAdapter
    from global_db_instance import get_global_db_adapter
    from ErrorCorrection import SmartErrorCorrector, ErrorInfo
except ImportError as e:
    print(f"导入错误: {e}")
    sys.exit(1)


class SQLHighlighter:
    """SQL语法高亮器"""
    
    def __init__(self, text_widget):
        self.text_widget = text_widget
        self.keywords = {
            'SELECT', 'FROM', 'WHERE', 'INSERT', 'UPDATE', 'DELETE', 
            'CREATE', 'DROP', 'ALTER', 'TABLE', 'INDEX', 'DATABASE',
            'INTO', 'VALUES', 'SET', 'AND', 'OR', 'NOT', 'NULL',
            'PRIMARY', 'KEY', 'FOREIGN', 'REFERENCES', 'UNIQUE',
            'ORDER', 'BY', 'GROUP', 'HAVING', 'LIMIT', 'OFFSET',
            'JOIN', 'INNER', 'LEFT', 'RIGHT', 'OUTER', 'ON', 'AS',
            'USE', 'LIST', 'DATABASES', 'SHOW'  # 添加数据库级操作关键字
        }
        
        # 配置语法高亮标签
        self.text_widget.tag_config("keyword", foreground="#0066CC", font=("Consolas", 10, "bold"))
        self.text_widget.tag_config("string", foreground="#009900")
        self.text_widget.tag_config("number", foreground="#FF6600")
        self.text_widget.tag_config("comment", foreground="#999999", font=("Consolas", 10, "italic"))
        
    def highlight(self):
        """高亮显示SQL语法"""
        content = self.text_widget.get(1.0, tk.END)
        
        # 清除之前的高亮
        for tag in ["keyword", "string", "number", "comment"]:
            self.text_widget.tag_remove(tag, 1.0, tk.END)
        
        # 高亮关键字
        for keyword in self.keywords:
            pattern = r'\b' + keyword + r'\b'
            for match in re.finditer(pattern, content, re.IGNORECASE):
                start = f"1.0+{match.start()}c"
                end = f"1.0+{match.end()}c"
                self.text_widget.tag_add("keyword", start, end)
        
        # 高亮字符串
        for match in re.finditer(r"'[^']*'|\"[^\"]*\"", content):
            start = f"1.0+{match.start()}c"
            end = f"1.0+{match.end()}c"
            self.text_widget.tag_add("string", start, end)
        
        # 高亮数字
        for match in re.finditer(r'\b\d+(?:\.\d+)?\b', content):
            start = f"1.0+{match.start()}c"
            end = f"1.0+{match.end()}c"
            self.text_widget.tag_add("number", start, end)
        
        # 高亮注释
        for match in re.finditer(r'--.*$', content, re.MULTILINE):
            start = f"1.0+{match.start()}c"
            end = f"1.0+{match.end()}c"
            self.text_widget.tag_add("comment", start, end)


class QueryResultTable:
    """查询结果表格组件"""
    
    def __init__(self, parent):
        self.parent = parent
        self.frame = ttk.Frame(parent)
        
        # 创建表格
        self.tree = ttk.Treeview(self.frame)
        
        # 滚动条
        v_scrollbar = ttk.Scrollbar(self.frame, orient="vertical", command=self.tree.yview)
        h_scrollbar = ttk.Scrollbar(self.frame, orient="horizontal", command=self.tree.xview)
        self.tree.configure(yscrollcommand=v_scrollbar.set, xscrollcommand=h_scrollbar.set)
        
        # 布局
        self.tree.grid(row=0, column=0, sticky="nsew")
        v_scrollbar.grid(row=0, column=1, sticky="ns")
        h_scrollbar.grid(row=1, column=0, sticky="ew")
        
        self.frame.grid_rowconfigure(0, weight=1)
        self.frame.grid_columnconfigure(0, weight=1)
    
    def display_results(self, columns, data):
        """显示查询结果"""
        # 清除之前的数据
        self.tree.delete(*self.tree.get_children())
        
        # 设置列
        self.tree["columns"] = columns
        self.tree["show"] = "headings"
        
        # 配置列
        for col in columns:
            self.tree.heading(col, text=col)
            self.tree.column(col, width=100, minwidth=50)
        
        # 插入数据
        for row in data:
            values = [row.get(col, '') for col in columns]
            self.tree.insert("", "end", values=values)
    
    def clear(self):
        """清空表格"""
        self.tree.delete(*self.tree.get_children())
        self.tree["columns"] = ()


class DatabaseExplorer:
    """数据库资源管理器"""
    
    def __init__(self, parent, gui_app):
        self.parent = parent
        self.gui_app = gui_app
        self.frame = ttk.Frame(parent)
        
        # 创建树形视图
        self.tree = ttk.Treeview(self.frame)
        self.tree.heading("#0", text="数据库对象")
        
        # 滚动条
        scrollbar = ttk.Scrollbar(self.frame, orient="vertical", command=self.tree.yview)
        self.tree.configure(yscrollcommand=scrollbar.set)
        
        # 布局
        self.tree.pack(side="left", fill="both", expand=True)
        scrollbar.pack(side="right", fill="y")
        
        # 绑定事件
        self.tree.bind("<Double-1>", self.on_double_click)
        self.tree.bind("<Button-1>", self.on_single_click)  # 添加单击事件
        
        # 刷新按钮
        refresh_btn = ttk.Button(self.frame, text="刷新", command=self.refresh)
        refresh_btn.pack(side="bottom", fill="x", pady=2)
        
        self.refresh()
    
    def refresh(self):
        """刷新数据库列表"""
        self.tree.delete(*self.tree.get_children())
        
        try:
            if hasattr(self.gui_app, 'storage_adapter') and self.gui_app.storage_adapter:
                # 获取所有数据库列表
                try:
                    # 使用LIST DATABASES操作获取所有数据库
                    databases = self.gui_app.storage_adapter.db_adapter.list_databases()
                    
                    for db_name in databases:
                        # 标记当前数据库
                        if db_name == self.gui_app.database_name:
                            db_text = f"📁 {db_name} (当前)"
                        else:
                            db_text = f"📁 {db_name}"
                        
                        db_item = self.tree.insert("", "end", text=db_text, 
                                                 values=("database", db_name))
                        
                        # 只为当前数据库获取表列表
                        if db_name == self.gui_app.database_name:
                            try:
                                # 通过适配器获取当前数据库的表列表
                                tables = self.gui_app.storage_adapter.get_current_database_tables()
                                for table in tables:
                                    self.tree.insert(db_item, "end", text=f"📋 {table}", 
                                                   values=("table", table, db_name))
                                self.tree.item(db_item, open=True)
                            except Exception as e:
                                self.tree.insert(db_item, "end", text=f"❌ 获取表列表失败: {e}", 
                                               values=("error",))
                        else:
                            # 为其他数据库添加占位符
                            self.tree.insert(db_item, "end", text="💭 点击切换到此数据库查看表", 
                                           values=("placeholder",))
                    
                    if not databases:
                        self.tree.insert("", "end", text="📂 无数据库", values=("empty",))
                        
                except Exception as e:
                    self.tree.insert("", "end", text=f"❌ 获取数据库列表失败: {e}", values=("error",))
        except Exception as e:
            self.tree.insert("", "end", text=f"❌ 连接失败: {e}", values=("error",))
    
    def on_single_click(self, event):
        """单击事件处理 - 数据库切换"""
        if not self.tree.selection():
            return
            
        item = self.tree.selection()[0]
        values = self.tree.item(item, "values")
        
        # 如果点击的是数据库节点且不是当前数据库，则切换
        if len(values) >= 2 and values[0] == "database":
            db_name = values[1]
            if db_name != self.gui_app.database_name:
                self.switch_database(db_name)
    
    def on_double_click(self, event):
        """双击事件处理"""
        if not self.tree.selection():
            return
            
        item = self.tree.selection()[0]
        values = self.tree.item(item, "values")
        
        if len(values) >= 2 and values[0] == "table":
            table_name = values[1]
            # 生成并执行SELECT语句
            sql = f"SELECT * FROM {table_name} LIMIT 50;"
            self.gui_app.sql_editor.delete(1.0, tk.END)
            self.gui_app.sql_editor.insert(1.0, sql)
            self.gui_app.execute_query()
        elif len(values) >= 2 and values[0] == "database":
            # 双击数据库节点也可以切换
            db_name = values[1]
            if db_name != self.gui_app.database_name:
                self.switch_database(db_name)
    
    def switch_database(self, db_name):
        """切换到指定数据库"""
        try:
            # 执行USE DATABASE语句
            sql = f"USE {db_name};"
            
            # 更新GUI应用的当前数据库名称
            old_db_name = self.gui_app.database_name
            self.gui_app.database_name = db_name
            
            # 执行切换
            success = self.gui_app.storage_adapter.db_adapter.use_database(db_name)
            
            if success:
                # 更新存储适配器的数据库名称
                self.gui_app.storage_adapter.database_name = db_name
                
                # 更新存储引擎实例
                self.gui_app.storage_adapter._update_current_database_storage()
                
                # 更新工具栏显示
                self.gui_app.connection_label.config(text=f"已连接: {db_name}")
                
                # 更新状态栏
                self.gui_app.status_label.config(text=f"已切换到数据库: {db_name}")
                
                # 刷新数据库资源管理器
                self.refresh()
                
                # 刷新语义分析器的表信息
                self.gui_app._refresh_semantic_analyzer_tables()
                
                print(f"[GUI] 成功切换到数据库: {db_name}")
            else:
                # 切换失败，恢复原数据库名称
                self.gui_app.database_name = old_db_name
                self.gui_app.status_label.config(text=f"切换数据库失败: {db_name}")
                
        except Exception as e:
            # 发生异常，恢复原数据库名称
            self.gui_app.database_name = old_db_name
            self.gui_app.status_label.config(text=f"切换数据库异常: {e}")
            print(f"[GUI] 切换数据库异常: {e}")


class DatabaseGUI:
    """数据库图形界面主应用"""
    
    def __init__(self, data_root="database", database_name="demo_db"):
        self.data_root = data_root
        self.database_name = database_name
        
        # 用户认证状态
        self.is_authenticated = False
        self.current_user = None
        
        # 按照demo的模式：直接初始化所有数据库组件（包括存储适配器） not found
        self.init_database_components()
        
        # 创建主窗口
        self.root = tk.Tk()
        self.root.title("数据库管理工具 - Database Management Tool")
        self.root.geometry("1200x800")
        self.root.minsize(800, 600)
        
        # 配置主题和样式
        self.setup_theme()
        
        # 显示登录对话框
        if not self.show_login_dialog():
            self.root.destroy()
            return
        
        # 创建界面
        self.create_menu()
        self.create_toolbar()
        self.create_main_interface()
        self.create_status_bar()
        
        # 查询队列（用于异步执行）
        self.query_queue = queue.Queue()
        self.root.after(100, self.process_query_results)
        
        # 状态变量
        self.is_executing = False
    
    def init_database_components(self):
        """初始化数据库组件（完全按照demo的模式）"""
        try:
            # 初始化SQL编译器组件
            self.lexical_analyzer = LexicalAnalyzer()
            self.syntax_analyzer = SyntaxAnalyzer()
            self.semantic_analyzer = SemanticAnalyzer()
            self.logical_plan_generator = LogicalPlanGenerator()
            self.physical_plan_optimizer = PhysicalPlanOptimizer()
            
            # 使用全局数据库适配器实例，避免多个DatabaseServer
            global_db_adapter = get_global_db_adapter(data_root=self.data_root)
            self.storage_adapter = StorageEngineAdapter(
                data_root=self.data_root,
                database_name=self.database_name,
                db_adapter=global_db_adapter
            )
            
            # 初始化查询执行器
            self.query_executor = QueryExecutor(storage_engine=self.storage_adapter)
            
            # 为语义分析器设置存储适配器
            self.semantic_analyzer.set_storage_adapter(self.storage_adapter)
            
            print(f"✅ 数据库组件初始化成功 - 数据库: {self.database_name}")
            
        except Exception as e:
            messagebox.showerror("初始化错误", f"数据库组件初始化失败: {e}")
            sys.exit(1)
    
    def show_login_dialog(self):
        """显示登录对话框"""
        login_window = tk.Toplevel(self.root)
        login_window.title("用户登录")
        login_window.geometry("350x200")
        login_window.resizable(False, False)
        login_window.transient(self.root)
        login_window.grab_set()
        
        # 居中显示
        login_window.update_idletasks()
        x = (login_window.winfo_screenwidth() // 2) - (login_window.winfo_width() // 2)
        y = (login_window.winfo_screenheight() // 2) - (login_window.winfo_height() // 2)
        login_window.geometry(f"+{x}+{y}")
        
        # 创建登录表单
        main_frame = ttk.Frame(login_window, padding="20")
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 标题
        title_label = ttk.Label(main_frame, text="数据库管理工具", font=("Arial", 16, "bold"))
        title_label.pack(pady=(0, 20))
        
        # 用户名
        ttk.Label(main_frame, text="用户名:").pack(anchor=tk.W)
        username_var = tk.StringVar(value="root")
        username_entry = ttk.Entry(main_frame, textvariable=username_var, width=30)
        username_entry.pack(pady=(5, 10), fill=tk.X)
        
        # 密码
        ttk.Label(main_frame, text="密码:").pack(anchor=tk.W)
        password_var = tk.StringVar(value="root12345")
        password_entry = ttk.Entry(main_frame, textvariable=password_var, show="*", width=30)
        password_entry.pack(pady=(5, 20), fill=tk.X)
        
        # 登录结果
        login_success = False
        
        def do_login():
            nonlocal login_success
            username = username_var.get().strip()
            password = password_var.get().strip()
            
            if not username or not password:
                messagebox.showerror("错误", "请输入用户名和密码")
                return
            
            try:
                # 按照demo的模式：直接使用已存在的存储适配器进行登录
                if self.storage_adapter.login(username, password):
                    self.is_authenticated = True
                    self.current_user = username
                    login_success = True
                    
                    login_window.destroy()
                    # 更新窗口标题
                    self.root.title(f"数据库管理工具 - {username}@{self.database_name}")
                    messagebox.showinfo("成功", f"用户 {username} 登录成功！")
                else:
                    messagebox.showerror("错误", "用户名或密码错误")
            except Exception as e:
                messagebox.showerror("错误", f"登录失败: {e}")
        
        def cancel_login():
            nonlocal login_success
            login_success = False
            login_window.destroy()
        
        # 按钮
        button_frame = ttk.Frame(main_frame)
        button_frame.pack(fill=tk.X)
        
        login_button = ttk.Button(button_frame, text="登录", command=do_login)
        login_button.pack(side=tk.RIGHT, padx=(10, 0))
        
        cancel_button = ttk.Button(button_frame, text="取消", command=cancel_login)
        cancel_button.pack(side=tk.RIGHT)
        
        # 绑定回车键
        def on_enter(event):
            do_login()
        
        username_entry.bind('<Return>', on_enter)
        password_entry.bind('<Return>', on_enter)
        
        # 设置焦点
        username_entry.focus()
        
        # 等待窗口关闭
        login_window.wait_window()
        
        return login_success
    
    def _refresh_semantic_analyzer_tables(self):
        """刷新语义分析器的表信息"""
        try:
            # 获取当前所有表
            table_list = self.storage_adapter.get_current_database_tables()
            
            # 为每个表加载结构信息
            for table_name in table_list:
                if table_name not in self.semantic_analyzer.predefined_tables:
                    self.semantic_analyzer._load_table_schema(table_name)
                    print(f"[GUI] 为语义分析器加载新表: {table_name}")
            
        except Exception as e:
            print(f"[GUI] 刷新语义分析器表信息失败: {e}")
    
    def setup_styles(self):
        """设置界面样式"""
        style = ttk.Style()
        
        # 设置主题
        try:
            style.theme_use("clam")
        except:
            pass
        
        # 自定义样式
        style.configure("Title.TLabel", font=("Arial", 12, "bold"))
        style.configure("Status.TLabel", relief="sunken", padding=3)
    
    def create_menu(self):
        """创建菜单栏"""
        menubar = tk.Menu(self.root)
        self.root.config(menu=menubar)
        
        # 文件菜单
        file_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="文件", menu=file_menu)
        file_menu.add_command(label="新建查询", command=self.new_query, accelerator="Ctrl+N")
        file_menu.add_command(label="打开文件", command=self.open_file, accelerator="Ctrl+O")
        file_menu.add_command(label="保存", command=self.save_file, accelerator="Ctrl+S")
        file_menu.add_separator()
        file_menu.add_command(label="退出", command=self.root.quit, accelerator="Ctrl+Q")
        
        # 编辑菜单
        edit_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="编辑", menu=edit_menu)
        edit_menu.add_command(label="撤销", command=lambda: self.sql_editor.edit_undo())
        edit_menu.add_command(label="重做", command=lambda: self.sql_editor.edit_redo())
        edit_menu.add_separator()
        edit_menu.add_command(label="格式化SQL", command=self.format_sql, accelerator="Ctrl+Shift+F")
        edit_menu.add_separator()
        edit_menu.add_command(label="复制行", command=self.duplicate_line, accelerator="Ctrl+D")
        edit_menu.add_command(label="注释切换", command=self.toggle_comment, accelerator="Ctrl+/")
        edit_menu.add_separator()
        edit_menu.add_command(label="查询历史", command=self.show_query_history, accelerator="Ctrl+H")
        
        # 查询菜单
        query_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="查询", menu=query_menu)
        query_menu.add_command(label="执行", command=self.execute_query, accelerator="F5")
        query_menu.add_command(label="执行选中", command=self.execute_selected, accelerator="F9")
        query_menu.add_separator()
        query_menu.add_command(label="停止执行", command=self.stop_query, accelerator="ESC")
        query_menu.add_separator()
        query_menu.add_command(label="查询历史", command=self.show_query_history, accelerator="Ctrl+H")
        query_menu.add_command(label="查询书签", command=self.show_bookmarks)
        
        # 数据库菜单
        database_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="数据库", menu=database_menu)
        database_menu.add_command(label="列出数据库", command=self.list_databases, accelerator="Ctrl+L")
        database_menu.add_command(label="创建数据库", command=self.create_database_dialog, accelerator="Ctrl+Shift+N")
        database_menu.add_command(label="删除数据库", command=self.drop_database_dialog, accelerator="Ctrl+Shift+D")
        database_menu.add_separator()
        database_menu.add_command(label="切换数据库", command=self.use_database_dialog, accelerator="Ctrl+U")
        
        # 工具菜单
        tools_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="工具", menu=tools_menu)
        tools_menu.add_command(label="刷新数据库", command=self.refresh_database)
        tools_menu.add_command(label="查看执行计划", command=self.show_execution_plan)
        
        # 用户菜单
        user_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label=f"用户({self.current_user})", menu=user_menu)
        user_menu.add_command(label="用户信息", command=self.show_user_info)
        user_menu.add_separator()
        user_menu.add_command(label="注销", command=self.logout)
        
        # 帮助菜单
        help_menu = tk.Menu(menubar, tearoff=0)
        menubar.add_cascade(label="帮助", menu=help_menu)
        help_menu.add_command(label="SQL语法", command=self.show_sql_help)
        help_menu.add_command(label="关于", command=self.show_about)
        
        # 绑定快捷键
        self.root.bind('<Control-n>', lambda e: self.new_query())
        self.root.bind('<Control-o>', lambda e: self.open_file())
        self.root.bind('<Control-s>', lambda e: self.save_file())
        self.root.bind('<Control-Shift-F>', lambda e: self.format_sql())  # Ctrl+Shift+F 格式化
        self.root.bind('<Control-d>', lambda e: self.duplicate_line())     # Ctrl+D 复制行
        self.root.bind('<Control-slash>', lambda e: self.toggle_comment()) # Ctrl+/ 注释切换
        self.root.bind('<Control-h>', lambda e: self.show_query_history()) # Ctrl+H 查询历史
        self.root.bind('<F5>', lambda e: self.execute_query())
        self.root.bind('<F9>', lambda e: self.execute_selected())
        self.root.bind('<Escape>', lambda e: self.stop_query())            # ESC 停止查询
        # 数据库操作快捷键
        self.root.bind('<Control-l>', lambda e: self.list_databases())     # Ctrl+L 列出数据库
        self.root.bind('<Control-Shift-N>', lambda e: self.create_database_dialog())  # Ctrl+Shift+N 创建数据库
        self.root.bind('<Control-Shift-D>', lambda e: self.drop_database_dialog())    # Ctrl+Shift+D 删除数据库
        self.root.bind('<Control-u>', lambda e: self.use_database_dialog()) # Ctrl+U 切换数据库
    
    def create_toolbar(self):
        """创建工具栏"""
        toolbar = ttk.Frame(self.root)
        toolbar.pack(side="top", fill="x", padx=2, pady=2)
        
        # 执行按钮
        self.execute_btn = ttk.Button(toolbar, text="▶ 执行", command=self.execute_query)
        self.execute_btn.pack(side="left", padx=2)
        
        # 停止按钮
        self.stop_btn = ttk.Button(toolbar, text="⏹ 停止", command=self.stop_query, state="disabled")
        self.stop_btn.pack(side="left", padx=2)
        
        ttk.Separator(toolbar, orient="vertical").pack(side="left", fill="y", padx=5)
        
        # 新建查询按钮
        ttk.Button(toolbar, text="📝 新建", command=self.new_query).pack(side="left", padx=2)
        
        # 打开文件按钮
        ttk.Button(toolbar, text="📂 打开", command=self.open_file).pack(side="left", padx=2)
        
        # 保存按钮
        ttk.Button(toolbar, text="💾 保存", command=self.save_file).pack(side="left", padx=2)
        
        ttk.Separator(toolbar, orient="vertical").pack(side="left", fill="y", padx=5)
        
        # 格式化按钮
        ttk.Button(toolbar, text="🎨 格式化", command=self.format_sql).pack(side="left", padx=2)
        
        # 刷新按钮
        ttk.Button(toolbar, text="🔄 刷新", command=self.refresh_database).pack(side="left", padx=2)
        
        ttk.Separator(toolbar, orient="vertical").pack(side="left", fill="y", padx=5)
        
        # 数据库操作按钮
        ttk.Button(toolbar, text="📋 列出数据库", command=self.list_databases).pack(side="left", padx=2)
        ttk.Button(toolbar, text="➕ 创建数据库", command=self.create_database_dialog).pack(side="left", padx=2)
        ttk.Button(toolbar, text="🔄 切换数据库", command=self.use_database_dialog).pack(side="left", padx=2)
        
        # 数据库信息
        ttk.Label(toolbar, text=f"📁 数据库: {self.database_name}", 
                 style="Title.TLabel").pack(side="right", padx=10)
    
    def create_main_interface(self):
        """创建主界面"""
        # 创建主面板
        main_paned = ttk.PanedWindow(self.root, orient="horizontal")
        main_paned.pack(fill="both", expand=True, padx=2, pady=2)
        
        # 左侧面板 - 数据库资源管理器
        left_frame = ttk.Frame(main_paned)
        main_paned.add(left_frame, weight=1)
        
        ttk.Label(left_frame, text="数据库资源管理器", style="Title.TLabel").pack(pady=5)
        self.db_explorer = DatabaseExplorer(left_frame, self)
        self.db_explorer.frame.pack(fill="both", expand=True, padx=5)
        
        # 右侧面板
        right_paned = ttk.PanedWindow(main_paned, orient="vertical")
        main_paned.add(right_paned, weight=4)
        
        # SQL编辑器面板
        editor_frame = ttk.Frame(right_paned)
        right_paned.add(editor_frame, weight=1)
        
        ttk.Label(editor_frame, text="SQL查询编辑器", style="Title.TLabel").pack(pady=5)
        
        # SQL编辑器
        editor_container = ttk.Frame(editor_frame)
        editor_container.pack(fill="both", expand=True, padx=5, pady=5)
        
        self.sql_editor = scrolledtext.ScrolledText(
            editor_container,
            height=12,
            font=("Consolas", 11),
            wrap=tk.NONE,
            undo=True,
            maxundo=50
        )
        self.sql_editor.pack(fill="both", expand=True)
        
        # 初始化SQL高亮器和查询历史
        self.sql_highlighter = SQLHighlighter(self.sql_editor)
        self.query_history = []
        self.history_index = -1
        
        # 绑定编辑器事件
        self.sql_editor.bind('<KeyRelease>', lambda e: self.sql_highlighter.highlight())
        self.sql_editor.bind('<Control-Return>', lambda e: self.execute_query())  # Ctrl+Enter 执行
        self.sql_editor.bind('<Control-Up>', lambda e: self.history_previous())   # Ctrl+Up 上一条历史
        self.sql_editor.bind('<Control-Down>', lambda e: self.history_next())     # Ctrl+Down 下一条历史
        
        # 插入示例SQL
        sample_sql = """-- 示例SQL查询
SELECT * FROM users LIMIT 10;

-- 创建表示例
-- CREATE TABLE example_table (
--     id INT PRIMARY KEY,
--     name VARCHAR(50),
--     created_at DATE
-- );"""
        self.sql_editor.insert(1.0, sample_sql)
        self.sql_highlighter.highlight()
        
        # 结果面板
        result_frame = ttk.Frame(right_paned)
        right_paned.add(result_frame, weight=1)
        
        # 创建垂直分隔的面板：上方是结果表格，下方是输出区域
        result_paned = ttk.PanedWindow(result_frame, orient="vertical")
        result_paned.pack(fill="both", expand=True)
        
        # 上方：查询结果区域
        top_result_frame = ttk.Frame(result_paned)
        result_paned.add(top_result_frame, weight=2)
        
        # 结果标签
        result_header = ttk.Frame(top_result_frame)
        result_header.pack(fill="x", pady=5)
        
        ttk.Label(result_header, text="查询结果", style="Title.TLabel").pack(side="left")
        self.result_info_label = ttk.Label(result_header, text="")
        self.result_info_label.pack(side="right")
        
        # 结果表格
        self.result_table = QueryResultTable(top_result_frame)
        self.result_table.frame.pack(fill="both", expand=True, padx=5, pady=5)
        
        # 下方：输出区域
        bottom_output_frame = ttk.Frame(result_paned)
        result_paned.add(bottom_output_frame, weight=1)
        
        # 输出区域标签
        output_header = ttk.Frame(bottom_output_frame)
        output_header.pack(fill="x", pady=5)
        
        ttk.Label(output_header, text="输出信息", style="Title.TLabel").pack(side="left")
        
        # 清空输出按钮
        clear_output_btn = ttk.Button(output_header, text="清空", command=self._clear_output, width=8)
        clear_output_btn.pack(side="right", padx=5)
        
        # 创建输出文本区域
        self.output_text = scrolledtext.ScrolledText(
            bottom_output_frame,
            height=8,
            font=("Consolas", 10),
            wrap=tk.WORD,
            state="disabled",
            bg="#f8f8f8"
        )
        self.output_text.pack(fill="both", expand=True, padx=5, pady=5)
        
        # 显示欢迎信息
        self._append_to_output("📋 数据库管理工具已启动")
        self._append_to_output(f"🔗 当前数据库: {self.database_name}")
        self._append_to_output("💡 提示: 编译错误和详细信息将在此处显示")
    
    def create_status_bar(self):
        """创建状态栏"""
        status_frame = ttk.Frame(self.root)
        status_frame.pack(side="bottom", fill="x")
        
        self.status_label = ttk.Label(status_frame, text="就绪", style="Status.TLabel")
        self.status_label.pack(side="left", fill="x", expand=True)
        
        self.connection_label = ttk.Label(status_frame, text=f"已连接: {self.database_name}", 
                                        style="Status.TLabel")
        self.connection_label.pack(side="right")
    
    def _append_to_output(self, message, add_timestamp=True):
        """向输出区域添加消息"""
        try:
            if hasattr(self, 'output_text'):
                if add_timestamp and message.strip():
                    from datetime import datetime
                    timestamp = datetime.now().strftime("%H:%M:%S")
                    formatted_message = f"[{timestamp}] {message}\n"
                else:
                    # 对于空行或不需要时间戳的消息，直接添加
                    formatted_message = f"{message}\n" if message else "\n"
                
                self.output_text.config(state="normal")
                self.output_text.insert(tk.END, formatted_message)
                self.output_text.see(tk.END)  # 滚动到底部
                self.output_text.config(state="disabled")
        except Exception as e:
            print(f"输出消息失败: {e}")
    
    def _clear_output(self):
        """清空输出区域"""
        try:
            if hasattr(self, 'output_text'):
                self.output_text.config(state="normal")
                self.output_text.delete(1.0, tk.END)
                self.output_text.config(state="disabled")
        except Exception as e:
            print(f"清空输出失败: {e}")
    
    def _display_compilation_error(self, error_message, detailed_error):
        """显示编译错误"""
        try:
            # 在输出区域显示错误
            self._append_to_output(f"❌ {error_message}")
            
            # 显示详细的智能纠错报告
            if detailed_error:
                # 添加分隔线
                self._append_to_output("", add_timestamp=False)
                
                # 将智能纠错报告按行分割并逐行显示，保持格式
                error_lines = detailed_error.split('\n')
                for line in error_lines:
                    if line.strip():  # 对于有内容的行
                        # 检查是否是标题行（包含=号的行）或特殊标记行
                        if ('=' in line and len(line.strip()) > 20) or line.startswith('🔍') or line.startswith('💡'):
                            self._append_to_output(line, add_timestamp=False)
                        else:
                            self._append_to_output(line, add_timestamp=False)
                    else:
                        self._append_to_output("", add_timestamp=False)  # 保持空行格式
                
                # 添加结束分隔线
                self._append_to_output("", add_timestamp=False)
            
            # 清空结果表格
            self.result_table.clear()
            self.result_info_label.config(text="编译失败")
            self.status_label.config(text=f"编译失败: {error_message}")
            
            # 重置执行状态
            self.is_executing = False
            self.execute_btn.config(state="normal")
            self.stop_btn.config(state="disabled")
            
        except Exception as e:
            print(f"显示编译错误失败: {e}")
    
    def _generate_smart_error_report(self, sql, smart_corrector, lexical_errors=None, syntax_errors=None, semantic_errors=None, tokens=None):
        """生成智能纠错报告"""
        try:
            # 清空之前的错误
            smart_corrector.clear_errors()
            
            # 创建模拟tokens用于词法分析（如果没有提供）
            if tokens is None:
                mock_tokens = []
                words = sql.replace(';', ' ; ').replace(',', ' , ').split()
                for word_idx, word in enumerate(words):
                    if word.upper() not in smart_corrector.sql_keywords and len(word) > 1 and word not in [';', ',', '(', ')']:
                        # 创建模拟token用于拼写检查
                        class MockTokenType:
                            def __init__(self, name):
                                self.name = name
                        
                        class MockToken:
                            def __init__(self, token_type, value, line, column):
                                self.type = token_type
                                self.value = value
                                self.line = line
                                self.column = column
                        
                        mock_tokens.append(MockToken(MockTokenType('IDENTIFIER'), word, 1, word_idx * 10))
                tokens = mock_tokens
            
            # 分析词法错误
            if lexical_errors or tokens:
                lexical_error_list = smart_corrector.analyze_lexical_errors(sql, tokens)
                for error in lexical_error_list:
                    smart_corrector.add_error(error)
            
            # 分析语法错误
            if syntax_errors:
                if isinstance(syntax_errors, str):
                    syntax_error_list = [syntax_errors]
                elif isinstance(syntax_errors, list):
                    syntax_error_list = syntax_errors
                else:
                    syntax_error_list = []
                
                syntax_analysis_errors = smart_corrector.analyze_syntax_errors(sql, syntax_error_list)
                for error in syntax_analysis_errors:
                    smart_corrector.add_error(error)
            
            # 分析语义错误（使用预定义的表和数据库）
            if semantic_errors:
                predefined_tables = {
                    'Students': ['id', 'name', 'age', 'major'],
                    'Teachers': ['id', 'name', 'department'],
                    'Courses': ['id', 'course_name', 'teacher_id'],
                    'users': ['id', 'username', 'password', 'email'],
                    'products': ['id', 'name', 'price', 'category'],
                    'orders': ['id', 'user_id', 'product_id', 'quantity']
                }
                predefined_databases = {'test_db', 'demo_db', 'hr_system', 'company_db', 'system'}
                
                # 尝试从存储适配器获取实际的表信息
                try:
                    if hasattr(self, 'storage_adapter') and self.storage_adapter:
                        actual_tables = self.storage_adapter.get_current_database_tables()
                        for table_name in actual_tables:
                            if table_name not in predefined_tables:
                                # 尝试获取表结构
                                try:
                                    # 这里可以添加获取实际表结构的代码
                                    predefined_tables[table_name] = ['id', 'name', 'value']  # 默认列
                                except:
                                    pass
                        
                        # 获取实际的数据库列表
                        try:
                            actual_databases = self.storage_adapter.db_adapter.list_databases()
                            predefined_databases.update(actual_databases)
                        except:
                            pass
                except:
                    pass
                
                semantic_analysis_errors = smart_corrector.analyze_semantic_errors(
                    semantic_errors, predefined_tables, predefined_databases
                )
                for error in semantic_analysis_errors:
                    smart_corrector.add_error(error)
            
            # 生成修复建议
            suggestions = smart_corrector.generate_correction_suggestions(sql, smart_corrector.errors)
            for suggestion in suggestions:
                smart_corrector.add_suggestion(suggestion)
            
            # 格式化错误报告（只显示错误部分，不显示修复建议）
            error_report = smart_corrector.format_error_report()
            
            # 只使用错误报告，不包含修复建议
            full_report = error_report
            
            # 如果没有发现错误，提供基本的SQL分析
            if "未发现错误" in error_report:
                lines = sql.split('\n')
                basic_report = "\n📝 SQL语句分析:\n" + "="*50 + "\n"
                
                for i, line in enumerate(lines[:5], 1):  # 只显示前5行
                    basic_report += f"  {i:2d}: {line.strip()}\n"
                
                if len(lines) > 5:
                    basic_report += f"  ... 还有 {len(lines) - 5} 行\n"
                
                basic_report += "\n💡 请检查SQL语法是否正确。"
                full_report = basic_report
            
            return full_report
            
        except Exception as e:
            # 如果智能纠错系统出错，回退到基本错误显示
            return f"⚠️ 智能纠错系统异常: {e}\n\n📝 基本错误信息:\n请检查SQL语法是否正确。"
    
    def _format_smart_error_report(self, sql, context):
        """格式化智能错误报告（保留向后兼容）"""
        try:
            # 简单的错误报告格式化
            lines = sql.split('\n')
            report = "SQL语句分析:\n"
            
            for i, line in enumerate(lines[:5], 1):  # 只显示前5行
                report += f"  {i:2d}: {line.strip()}\n"
            
            if len(lines) > 5:
                report += f"  ... 还有 {len(lines) - 5} 行\n"
            
            report += "\n请检查SQL语法是否正确。"
            return report
            
        except Exception as e:
            return f"无法分析SQL语句: {e}"
    
    def execute_query(self):
        """执行SQL查询"""
        if self.is_executing:
            messagebox.showwarning("提示", "正在执行查询，请等待完成")
            return
        
        sql = self.sql_editor.get(1.0, tk.END).strip()
        if not sql:
            messagebox.showwarning("提示", "请输入SQL语句")
            return
        
        # 保存到历史记录
        if sql not in self.query_history:
            self.query_history.append(sql)
            # 限制历史记录数量
            if len(self.query_history) > 50:
                self.query_history.pop(0)
        self.history_index = len(self.query_history) - 1
        
        # 开始执行
        self.is_executing = True
        self.execute_btn.config(state="disabled")
        self.stop_btn.config(state="normal")
        self.status_label.config(text="正在执行查询...")
        
        # 在新线程中执行查询
        threading.Thread(target=self._execute_query_thread, args=(sql,), daemon=True).start()
    
    def _execute_query_thread(self, sql):
        """在独立线程中执行查询"""
        try:
            start_time = datetime.now()
            
            # 创建智能纠错器
            smart_corrector = SmartErrorCorrector()
            
            # 词法分析
            tokens = self.lexical_analyzer.analyze(sql)
            
            # 检查词法分析错误
            if self.lexical_analyzer.has_errors():
                error_message = "词法分析失败"
                # 进行智能纠错分析
                detailed_error = self._generate_smart_error_report(sql, smart_corrector, 
                                                                 lexical_errors=self.lexical_analyzer.get_error_report(),
                                                                 tokens=tokens)
                
                # 在主线程中显示详细错误
                self.root.after(0, self._display_compilation_error, error_message, detailed_error)
                return
            
            # 语法分析
            success = self.syntax_analyzer.analyze(tokens)
            if not success:
                error_message = "语法分析失败"
                # 进行智能纠错分析
                syntax_errors = self.syntax_analyzer.get_error_report() if hasattr(self.syntax_analyzer, 'get_error_report') else []
                detailed_error = self._generate_smart_error_report(sql, smart_corrector,
                                                                 syntax_errors=syntax_errors,
                                                                 tokens=tokens)
                
                # 在主线程中显示详细错误
                self.root.after(0, self._display_compilation_error, error_message, detailed_error)
                return
            
            # 刷新语义分析器的表信息（确保能识别新创建的表）
            self._refresh_semantic_analyzer_tables()
            
            # 语义分析
            quadruples, symbol_table, errors = self.semantic_analyzer.analyze(tokens)
            if errors:
                error_message = "语义分析失败"
                # 进行智能纠错分析
                detailed_error = self._generate_smart_error_report(sql, smart_corrector,
                                                                 semantic_errors=errors,
                                                                 tokens=tokens)
                
                # 在主线程中显示详细错误
                self.root.after(0, self._display_compilation_error, error_message, detailed_error)
                return
            
            # 生成逻辑计划
            logical_plan = self.logical_plan_generator.generate_logical_plan(quadruples, symbol_table)
            if not logical_plan:
                error_message = "逻辑计划生成失败"
                detailed_error = "无法生成有效的逻辑执行计划，请检查SQL语句的逻辑结构。"
                
                # 在主线程中显示详细错误
                self.root.after(0, self._display_compilation_error, error_message, detailed_error)
                return
            
            # 优化物理计划
            physical_plan = self.physical_plan_optimizer.optimize_to_physical_plan(logical_plan)
            
            # 执行查询
            from ExecutionEngine.types import ExecutionContext
            context = ExecutionContext()
            results = []
            for batch in self.query_executor.execute_plan(physical_plan, context):
                results.extend(batch)
            
            # 计算执行时间
            execution_time = (datetime.now() - start_time).total_seconds()
            
            # 将结果放入队列
            self.query_queue.put({
                'type': 'success',
                'results': results,
                'execution_time': execution_time,
                'sql': sql
            })
            
        except Exception as e:
            # 将错误放入队列
            self.query_queue.put({
                'type': 'error',
                'error': str(e),
                'sql': sql
            })
    
    def process_query_results(self):
        """处理查询结果"""
        try:
            while True:
                result = self.query_queue.get_nowait()
                
                if result['type'] == 'success':
                    self._display_success_result(result)
                elif result['type'] == 'error':
                    self._display_error_result(result)
                elif result['type'] == 'batch_complete':
                    self._display_batch_results(result)
                elif result['type'] == 'batch_error':
                    self._display_batch_error(result)
                
                # 重置执行状态
                self.is_executing = False
                self.execute_btn.config(state="normal")
                self.stop_btn.config(state="disabled")
                
        except queue.Empty:
            pass
        
        # 继续处理
        self.root.after(100, self.process_query_results)
    
    def _display_success_result(self, result):
        """显示成功结果"""
        results = result['results']
        execution_time = result['execution_time']
        sql = result.get('sql', '').strip().upper()
        
        # 检查是否是USE DATABASE语句
        print(f"[DEBUG] 检查SQL: {sql}")
        print(f"[DEBUG] 是否匹配USE: {sql.startswith('USE ')}")
        print(f"[DEBUG] 不是USE DATABASE: {not sql.startswith('USE DATABASE')}")
        if sql.startswith('USE ') and not sql.startswith('USE DATABASE'):
            print(f"[DEBUG] 检测到USE语句，开始处理数据库切换")
            # 处理USE DATABASE语句的成功执行
            self._handle_use_database_success(sql, results)
        
        if isinstance(results, list) and len(results) > 0:
            # 查询结果
            if isinstance(results[0], dict):
                columns = list(results[0].keys())
                self.result_table.display_results(columns, results)
                
                info_text = f"查询成功 | {len(results)} 行 | 耗时: {execution_time:.3f}秒"
                self.result_info_label.config(text=info_text)
                self.status_label.config(text=f"查询完成 - {len(results)} 行结果")
                
                # 在输出区域显示成功信息
                self._append_to_output(f"✅ 查询执行成功")
                self._append_to_output(f"📊 返回 {len(results)} 行数据，耗时 {execution_time:.3f} 秒")
            else:
                # 非查询操作结果
                self.result_table.clear()
                info_text = f"操作成功 | 耗时: {execution_time:.3f}秒"
                self.result_info_label.config(text=info_text)
                self.status_label.config(text="操作完成")
                
                # 在输出区域显示成功信息
                self._append_to_output(f"✅ SQL语句执行成功")
                self._append_to_output(f"⏱️ 执行耗时 {execution_time:.3f} 秒")
        else:
            # 空结果
            self.result_table.clear()
            info_text = f"操作成功 | 无返回结果 | 耗时: {execution_time:.3f}秒"
            self.result_info_label.config(text=info_text)
            self.status_label.config(text="操作完成")
            
            # 在输出区域显示成功信息
            self._append_to_output(f"✅ SQL语句执行成功")
            self._append_to_output(f"📝 无返回结果，耗时 {execution_time:.3f} 秒")
        
        # 刷新数据库资源管理器
        self.db_explorer.refresh()
    
    def _handle_use_database_success(self, sql, results):
        """处理USE DATABASE语句成功执行后的GUI更新"""
        try:
            print(f"[DEBUG] 处理USE语句: {sql}")
            # 从SQL语句中提取数据库名称
            # SQL格式: USE database_name;
            parts = sql.replace(';', '').split()
            print(f"[DEBUG] SQL分割结果: {parts}")
            if len(parts) >= 2:
                new_db_name = parts[1].lower()
                print(f"[DEBUG] 提取的数据库名: {new_db_name}")
                
                # 更新GUI应用的当前数据库名称
                old_db_name = self.database_name
                print(f"[DEBUG] 旧数据库名: {old_db_name}")
                self.database_name = new_db_name
                print(f"[DEBUG] 已更新GUI数据库名为: {self.database_name}")
                
                # 更新存储适配器的数据库名称
                self.storage_adapter.database_name = new_db_name
                print(f"[DEBUG] 已更新存储适配器数据库名")
                
                # 更新存储引擎实例
                self.storage_adapter._update_current_database_storage()
                print(f"[DEBUG] 已更新存储引擎实例")
                
                # 更新工具栏显示（连接标签）
                print(f"[DEBUG] 更新连接标签为: 已连接: {new_db_name}")
                self.connection_label.config(text=f"已连接: {new_db_name}")
                print(f"[DEBUG] 连接标签已更新")
                
                # 更新状态栏
                self.status_label.config(text=f"已切换到数据库: {new_db_name}")
                print(f"[DEBUG] 状态栏已更新")
                
                # 刷新语义分析器的表信息
                self._refresh_semantic_analyzer_tables()
                print(f"[DEBUG] 语义分析器已刷新")
                
                print(f"[GUI] SQL执行切换数据库成功: {old_db_name} -> {new_db_name}")
                
        except Exception as e:
            print(f"[GUI] 处理USE DATABASE成功结果时发生异常: {e}")
            import traceback
            traceback.print_exc()
    
    def _display_error_result(self, result):
        """显示错误结果"""
        error = result['error']
        
        self.result_table.clear()
        self.result_info_label.config(text="查询失败")
        self.status_label.config(text="查询失败")
        
        # 显示错误对话框
        messagebox.showerror("查询错误", f"SQL执行失败:\n\n{error}")
    
    def _display_batch_results(self, result):
        """显示批量执行结果"""
        print(f"[DEBUG] 显示批量结果，result类型: {type(result)}")
        print(f"[DEBUG] result keys: {result.keys() if isinstance(result, dict) else 'Not a dict'}")
        
        results = result.get('results', [])
        total_execution_time = result.get('total_execution_time', 0)
        total_statements = result.get('total_statements', 0)
        
        print(f"[DEBUG] results数量: {len(results)}")
        print(f"[DEBUG] 总语句数: {total_statements}")
        
        # 统计成功和失败数量
        success_count = sum(1 for r in results if r.get('success', False))
        failed_count = total_statements - success_count
        
        # 清空结果表格
        self.result_table.clear()
        
        # 创建批量执行结果摘要
        summary_data = []
        for i, r in enumerate(results):
            print(f"[DEBUG] 处理结果{i}: {r.keys() if isinstance(r, dict) else type(r)}")
            
            status = "✅ 成功" if r.get('success', False) else "❌ 失败"
            error_msg = r.get('error', '') if not r.get('success', False) else ''
            result_count = len(r.get('results', [])) if r.get('success', False) else 0
            
            summary_data.append({
                '序号': r.get('index', i + 1),  # 使用get方法，提供默认值
                'SQL语句': (r.get('sql', '')[:50] + '...') if len(r.get('sql', '')) > 50 else r.get('sql', ''),
                '状态': status,
                '耗时(秒)': f"{r.get('execution_time', 0):.3f}",
                '结果行数': result_count if r.get('success', False) else '',
                '错误信息': (error_msg[:30] + '...') if len(error_msg) > 30 else error_msg
            })
        
        # 显示摘要结果
        if summary_data:
            columns = list(summary_data[0].keys())
            self.result_table.display_results(columns, summary_data)
        
        # 更新信息标签
        info_text = f"批量执行完成 | 总计: {total_statements} 条 | 成功: {success_count} 条 | 失败: {failed_count} 条 | 总耗时: {total_execution_time:.3f}秒"
        self.result_info_label.config(text=info_text)
        
        # 更新状态标签
        if failed_count > 0:
            self.status_label.config(text=f"批量执行完成 - {success_count}/{total_statements} 条成功")
        else:
            self.status_label.config(text=f"批量执行完成 - 全部 {success_count} 条成功")
        
        # 如果有失败的语句，显示详细错误信息
        if failed_count > 0:
            error_details = []
            for r in results:
                if not r['success']:
                    error_details.append(f"第{r['index']}条: {r['sql']}\n错误: {r.get('error', '未知错误')}")
            
            if error_details:
                error_message = f"批量执行中有 {failed_count} 条语句失败:\n\n" + "\n\n".join(error_details[:5])
                if len(error_details) > 5:
                    error_message += f"\n\n... 还有 {len(error_details) - 5} 条错误"
                
                messagebox.showwarning("批量执行警告", error_message)
        
        # 刷新数据库资源管理器
        self.db_explorer.refresh()
    
    def _display_batch_error(self, result):
        """显示批量执行错误"""
        error = result['error']
        results = result.get('results', [])
        
        # 清空结果表格
        self.result_table.clear()
        
        # 显示已执行的结果（如果有的话）
        if results:
            success_count = sum(1 for r in results if r['success'])
            failed_count = len(results) - success_count
            
            # 创建已执行结果摘要
            summary_data = []
            for r in results:
                status = "✅ 成功" if r['success'] else "❌ 失败"
                error_msg = r.get('error', '') if not r['success'] else ''
                result_count = len(r.get('results', [])) if r['success'] else 0
                
                summary_data.append({
                    '序号': r['index'],
                    'SQL语句': r['sql'][:50] + '...' if len(r['sql']) > 50 else r['sql'],
                    '状态': status,
                    '耗时(秒)': f"{r['execution_time']:.3f}",
                    '结果行数': result_count if r['success'] else '',
                    '错误信息': error_msg[:30] + '...' if len(error_msg) > 30 else error_msg
                })
            
            # 显示已执行的结果
            if summary_data:
                columns = list(summary_data[0].keys())
                self.result_table.display_results(columns, summary_data)
            
            info_text = f"批量执行中断 | 已执行: {len(results)} 条 | 成功: {success_count} 条 | 失败: {failed_count} 条"
            self.result_info_label.config(text=info_text)
        else:
            self.result_info_label.config(text="批量执行失败")
        
        self.status_label.config(text="批量执行失败")
        
        # 显示错误对话框
        messagebox.showerror("批量执行错误", f"批量SQL执行失败:\n\n{error}")
    
    def execute_selected(self):
        """执行选中的SQL（支持多行执行）"""
        try:
            selected_text = self.sql_editor.get(tk.SEL_FIRST, tk.SEL_LAST).strip()
            if selected_text:
                # 解析多条SQL语句
                sql_statements = self._parse_multiple_sql(selected_text)
                
                if len(sql_statements) == 1:
                    # 单条语句，直接执行（不替换编辑器内容）
                    self._execute_single_sql(selected_text)
                else:
                    # 多条语句，批量执行
                    self._execute_multiple_sql(sql_statements)
            else:
                messagebox.showwarning("提示", "请先选择要执行的SQL语句")
        except tk.TclError:
            messagebox.showwarning("提示", "请先选择要执行的SQL语句")
    
    def _parse_multiple_sql(self, text):
        """解析多条SQL语句，保留分号"""
        statements = []
        current_statement = ""
        
        # 按行处理，避免在字符串中的分号被误分割
        lines = text.split('\n')
        
        for line in lines:
            line = line.strip()
            
            # 跳过空行和注释行
            if not line or line.startswith('--') or line.startswith('#'):
                continue
            
            current_statement += " " + line if current_statement else line
            
            # 检查是否以分号结尾（简单检查，不处理字符串内的分号）
            if line.endswith(';'):
                if current_statement.strip():
                    statements.append(current_statement.strip())
                current_statement = ""
        
        # 如果最后一条语句没有分号，也添加进去
        if current_statement.strip():
            statements.append(current_statement.strip())
        
        return statements
    
    def _execute_single_sql(self, sql):
        """执行单条SQL语句（不修改编辑器内容）"""
        if self.is_executing:
            messagebox.showwarning("提示", "正在执行查询，请等待完成")
            return
        
        if not sql.strip():
            messagebox.showwarning("提示", "请输入SQL语句")
            return
        
        # 保存到历史记录
        if sql not in self.query_history:
            self.query_history.append(sql)
            # 限制历史记录数量
            if len(self.query_history) > 50:
                self.query_history.pop(0)
        self.history_index = len(self.query_history) - 1
        
        # 开始执行
        self.is_executing = True
        self.execute_btn.config(state="disabled")
        self.stop_btn.config(state="normal")
        self.status_label.config(text="正在执行查询...")
        
        # 在新线程中执行查询
        threading.Thread(target=self._execute_query_thread, args=(sql,), daemon=True).start()
    
    def _execute_multiple_sql(self, sql_statements):
        """执行多条SQL语句"""
        if self.is_executing:
            messagebox.showwarning("提示", "正在执行查询，请等待完成")
            return
        
        if not sql_statements:
            messagebox.showwarning("提示", "没有找到有效的SQL语句")
            return
        
        # 开始批量执行
        self.is_executing = True
        self.execute_btn.config(state="disabled")
        self.stop_btn.config(state="normal")
        self.status_label.config(text=f"正在批量执行 {len(sql_statements)} 条SQL语句...")
        
        # 清空之前的结果
        self.result_table.clear()
        self.result_info_label.config(text="")
        
        # 在新线程中执行批量查询
        threading.Thread(target=self._execute_multiple_sql_thread, args=(sql_statements,), daemon=True).start()
    
    def _execute_multiple_sql_thread(self, sql_statements):
        """在独立线程中执行多条SQL语句"""
        print(f"[DEBUG] 开始批量执行，共{len(sql_statements)}条SQL语句")
        results = []
        total_start_time = datetime.now()
        
        try:
            for i, sql in enumerate(sql_statements, 1):
                if not self.is_executing:  # 检查是否被停止
                    break
                
                print(f"[DEBUG] 开始执行第{i}条SQL: {sql[:50]}...")
                
                # 更新状态（同步更新）
                def update_status():
                    self.status_label.config(text=f"正在执行第 {i}/{len(sql_statements)} 条SQL语句...")
                
                self.root.after(0, update_status)
                
                # 等待状态更新完成
                import time
                time.sleep(0.1)
                
                try:
                    start_time = datetime.now()
                    
                    # 词法分析
                    tokens = self.lexical_analyzer.analyze(sql)
                    
                    # 语法分析
                    success = self.syntax_analyzer.analyze(tokens)
                    if not success:
                        raise Exception("语法分析失败")
                    
                    # 刷新语义分析器的表信息（同步执行）
                    def refresh_tables():
                        self._refresh_semantic_analyzer_tables()
                    
                    self.root.after(0, refresh_tables)
                    time.sleep(0.1)  # 等待刷新完成
                    
                    # 语义分析
                    quadruples, symbol_table, errors = self.semantic_analyzer.analyze(tokens)
                    if errors:
                        raise Exception(f"语义分析失败: {', '.join(errors)}")
                    
                    # 生成逻辑计划
                    logical_plan = self.logical_plan_generator.generate_logical_plan(quadruples, symbol_table)
                    if not logical_plan:
                        raise Exception("逻辑计划生成失败")
                    
                    # 优化物理计划
                    physical_plan = self.physical_plan_optimizer.optimize_to_physical_plan(logical_plan)
                    
                    # 执行查询
                    from ExecutionEngine.types import ExecutionContext
                    context = ExecutionContext()
                    query_results = []
                    for batch in self.query_executor.execute_plan(physical_plan, context):
                        query_results.extend(batch)
                    
                    # 创建查询结果对象（模拟单行执行的返回格式）
                    class QueryResult:
                        def __init__(self, success, data=None, error_message=None):
                            self.success = success
                            self.data = data
                            self.error_message = error_message
                    
                    query_result = QueryResult(True, query_results)
                    
                    end_time = datetime.now()
                    execution_time = (end_time - start_time).total_seconds()
                    
                    # 记录结果
                    if query_result and query_result.success:
                        result_info = {
                            'sql': sql,
                            'success': True,
                            'results': query_result.data if query_result.data else [],
                            'execution_time': execution_time,
                            'index': i
                        }
                        print(f"[DEBUG] 第{i}条SQL成功: {sql[:30]}...")
                    else:
                        error_msg = query_result.error_message if query_result else "未知错误"
                        result_info = {
                            'sql': sql,
                            'success': False,
                            'error': error_msg,
                            'execution_time': execution_time,
                            'index': i
                        }
                        print(f"[DEBUG] 第{i}条SQL失败: {sql[:30]}... 错误: {error_msg}")
                    
                    results.append(result_info)
                    
                    # 强制等待一下，确保操作完成
                    time.sleep(0.05)
                    
                except Exception as e:
                    end_time = datetime.now()
                    execution_time = (end_time - start_time).total_seconds()
                    
                    result_info = {
                        'sql': sql,
                        'success': False,
                        'error': str(e),
                        'execution_time': execution_time,
                        'index': i
                    }
                    results.append(result_info)
                    print(f"[DEBUG] SQL执行异常 - 第{i}条: {sql[:50]}... 错误: {e}")
                    
                    # 即使出错也等待一下再继续
                    time.sleep(0.05)
            
            total_end_time = datetime.now()
            total_execution_time = (total_end_time - total_start_time).total_seconds()
            
            # 将结果发送到主线程
            batch_result = {
                'type': 'batch_complete',
                'results': results,
                'total_execution_time': total_execution_time,
                'total_statements': len(sql_statements)
            }
            
            print(f"[DEBUG] 批量执行完成，发送结果到队列")
            print(f"[DEBUG] 结果数量: {len(results)}, 总语句数: {len(sql_statements)}")
            self.query_queue.put(batch_result)
            
        except Exception as e:
            # 发送批量执行错误
            error_result = {
                'type': 'batch_error',
                'error': str(e),
                'results': results
            }
            self.query_queue.put(error_result)
    
    def stop_query(self):
        """停止查询"""
        # 注意：这里只是界面状态重置，实际的查询停止需要更复杂的实现
        self.is_executing = False
        self.execute_btn.config(state="normal")
        self.stop_btn.config(state="disabled")
        self.status_label.config(text="查询已停止")
    
    def new_query(self):
        """新建查询"""
        if messagebox.askyesno("确认", "是否清空当前编辑器内容？"):
            self.sql_editor.delete(1.0, tk.END)
            self.result_table.clear()
            self.result_info_label.config(text="")
            self.status_label.config(text="就绪")
            self._clear_output()
            self._append_to_output("📝 新建查询会话已创建")
    
    def open_file(self):
        """打开SQL文件"""
        filename = filedialog.askopenfilename(
            title="打开SQL文件",
            filetypes=[("SQL文件", "*.sql"), ("文本文件", "*.txt"), ("所有文件", "*.*")]
        )
        
        if filename:
            try:
                with open(filename, 'r', encoding='utf-8') as f:
                    content = f.read()
                
                self.sql_editor.delete(1.0, tk.END)
                self.sql_editor.insert(1.0, content)
                self.sql_highlighter.highlight()
                
                self.status_label.config(text=f"已打开文件: {os.path.basename(filename)}")
                
            except Exception as e:
                messagebox.showerror("错误", f"打开文件失败: {e}")
    
    def save_file(self):
        """保存SQL文件"""
        filename = filedialog.asksaveasfilename(
            title="保存SQL文件",
            defaultextension=".sql",
            filetypes=[("SQL文件", "*.sql"), ("文本文件", "*.txt"), ("所有文件", "*.*")]
        )
        
        if filename:
            try:
                content = self.sql_editor.get(1.0, tk.END)
                with open(filename, 'w', encoding='utf-8') as f:
                    f.write(content)
                
                self.status_label.config(text=f"已保存文件: {os.path.basename(filename)}")
                
            except Exception as e:
                messagebox.showerror("错误", f"保存文件失败: {e}")
    
    def format_sql(self):
        """智能格式化SQL - 保持表名和列名原样"""
        content = self.sql_editor.get(1.0, tk.END).strip()
        if not content:
            return
        
        try:
            # SQL关键字列表（只格式化这些）
            keywords = [
                'SELECT', 'FROM', 'WHERE', 'ORDER BY', 'GROUP BY', 'HAVING', 
                'INSERT', 'UPDATE', 'DELETE', 'CREATE', 'DROP', 'ALTER',
                'JOIN', 'INNER JOIN', 'LEFT JOIN', 'RIGHT JOIN', 'FULL JOIN',
                'AND', 'OR', 'NOT', 'IN', 'EXISTS', 'LIKE', 'BETWEEN',
                'LIMIT', 'OFFSET', 'UNION', 'DISTINCT', 'AS', 'ON'
            ]
            
            # 分割SQL为词汇
            import re
            # 保护字符串字面量
            strings = []
            temp_content = content
            
            # 提取字符串字面量
            string_pattern = r"'[^']*'|\"[^\"]*\""
            for match in re.finditer(string_pattern, temp_content):
                placeholder = f'__STRING_{len(strings)}__'
                strings.append(match.group())
                temp_content = temp_content[:match.start()] + placeholder + temp_content[match.end():]
            
            # 格式化关键字（大小写不敏感匹配，但只改变关键字）
            formatted = temp_content
            for keyword in sorted(keywords, key=len, reverse=True):  # 长的先匹配
                pattern = r'\b' + re.escape(keyword.lower()) + r'\b'
                formatted = re.sub(pattern, keyword, formatted, flags=re.IGNORECASE)
            
            # 添加换行符提高可读性
            major_keywords = ['SELECT', 'FROM', 'WHERE', 'ORDER BY', 'GROUP BY', 'HAVING']
            for keyword in major_keywords:
                if keyword in formatted:
                    formatted = formatted.replace(keyword, f'\n{keyword}')
            
            # 恢复字符串字面量
            for i, string in enumerate(strings):
                formatted = formatted.replace(f'__STRING_{i}__', string)
            
            # 清理格式
            lines = []
            for line in formatted.split('\n'):
                line = line.strip()
                if line:
                    # 为SELECT子句添加适当缩进
                    if line.startswith((',')) and lines:
                        line = '    ' + line
                    lines.append(line)
            
            formatted = '\n'.join(lines)
            
            # 更新编辑器内容
            self.sql_editor.delete(1.0, tk.END)
            self.sql_editor.insert(1.0, formatted)
            self.sql_highlighter.highlight()
            
            self.status_label.config(text="SQL格式化完成")
            
        except Exception as e:
            messagebox.showwarning("格式化警告", f"SQL格式化部分完成: {e}")
    
    def duplicate_line(self):
        """复制当前行"""
        try:
            # 获取当前光标位置
            current_pos = self.sql_editor.index(tk.INSERT)
            line_start = current_pos.split('.')[0] + '.0'
            line_end = current_pos.split('.')[0] + '.end'
            
            # 获取当前行内容
            line_content = self.sql_editor.get(line_start, line_end)
            
            # 在行末插入换行和复制的内容
            self.sql_editor.insert(line_end, '\n' + line_content)
            self.status_label.config(text="行已复制")
            
        except Exception as e:
            messagebox.showwarning("复制失败", f"无法复制行: {e}")
    
    def toggle_comment(self):
        """切换注释状态"""
        try:
            # 获取选中文本，如果没有选中则操作当前行
            try:
                selected_text = self.sql_editor.get(tk.SEL_FIRST, tk.SEL_LAST)
                start_pos = self.sql_editor.index(tk.SEL_FIRST)
                end_pos = self.sql_editor.index(tk.SEL_LAST)
            except tk.TclError:
                # 没有选中文本，操作当前行
                current_pos = self.sql_editor.index(tk.INSERT)
                line_num = current_pos.split('.')[0]
                start_pos = f"{line_num}.0"
                end_pos = f"{line_num}.end"
                selected_text = self.sql_editor.get(start_pos, end_pos)
            
            # 判断是否已经注释
            lines = selected_text.split('\n')
            is_commented = all(line.strip().startswith('--') or line.strip() == '' for line in lines if line.strip())
            
            # 切换注释状态
            if is_commented:
                # 取消注释
                new_lines = []
                for line in lines:
                    if line.strip().startswith('--'):
                        # 移除 -- 及其后的一个空格（如果有）
                        line = line.replace('--', '', 1)
                        if line.startswith(' '):
                            line = line[1:]
                    new_lines.append(line)
            else:
                # 添加注释
                new_lines = []
                for line in lines:
                    if line.strip():
                        # 在行首添加 --
                        stripped = line.lstrip()
                        indent = line[:len(line) - len(stripped)]
                        new_lines.append(f"{indent}-- {stripped}")
                    else:
                        new_lines.append(line)
            
            # 替换内容
            new_text = '\n'.join(new_lines)
            self.sql_editor.delete(start_pos, end_pos)
            self.sql_editor.insert(start_pos, new_text)
            
            action = "取消注释" if is_commented else "添加注释"
            self.status_label.config(text=f"{action}完成")
            
        except Exception as e:
            messagebox.showwarning("注释失败", f"无法切换注释: {e}")
    
    def show_query_history(self):
        """显示查询历史"""
        history_window = tk.Toplevel(self.root)
        history_window.title("查询历史")
        history_window.geometry("600x400")
        
        # 创建历史列表
        frame = ttk.Frame(history_window)
        frame.pack(fill="both", expand=True, padx=10, pady=10)
        
        # 列表框
        listbox_frame = ttk.Frame(frame)
        listbox_frame.pack(fill="both", expand=True)
        
        scrollbar = ttk.Scrollbar(listbox_frame)
        scrollbar.pack(side="right", fill="y")
        
        history_listbox = tk.Listbox(listbox_frame, yscrollcommand=scrollbar.set, font=("Consolas", 10))
        history_listbox.pack(side="left", fill="both", expand=True)
        scrollbar.config(command=history_listbox.yview)
        
        # 填充历史记录
        for i, query in enumerate(self.query_history):
            # 只显示前50个字符
            display_text = query.replace('\n', ' ').strip()
            if len(display_text) > 50:
                display_text = display_text[:47] + "..."
            history_listbox.insert(tk.END, f"{i+1}. {display_text}")
        
        # 按钮框架
        button_frame = ttk.Frame(frame)
        button_frame.pack(fill="x", pady=(10, 0))
        
        def use_selected():
            selection = history_listbox.curselection()
            if selection:
                query = self.query_history[selection[0]]
                self.sql_editor.delete(1.0, tk.END)
                self.sql_editor.insert(1.0, query)
                history_window.destroy()
                self.status_label.config(text="历史查询已加载")
        
        def clear_history():
            if messagebox.askyesno("确认", "确定要清空查询历史吗？"):
                self.query_history.clear()
                history_listbox.delete(0, tk.END)
                self.status_label.config(text="查询历史已清空")
        
        ttk.Button(button_frame, text="使用选中", command=use_selected).pack(side="left", padx=(0, 5))
        ttk.Button(button_frame, text="清空历史", command=clear_history).pack(side="left", padx=(0, 5))
        ttk.Button(button_frame, text="关闭", command=history_window.destroy).pack(side="right")
        
        # 双击使用
        history_listbox.bind('<Double-1>', lambda e: use_selected())
    
    def show_bookmarks(self):
        """显示查询书签"""
        bookmark_window = tk.Toplevel(self.root)
        bookmark_window.title("查询书签")
        bookmark_window.geometry("700x500")
        
        # 初始化书签列表（如果不存在）
        if not hasattr(self, 'query_bookmarks'):
            self.query_bookmarks = []
        
        frame = ttk.Frame(bookmark_window)
        frame.pack(fill="both", expand=True, padx=10, pady=10)
        
        # 创建树形视图
        columns = ('名称', '查询', '创建时间')
        tree = ttk.Treeview(frame, columns=columns, show='headings', height=15)
        
        tree.heading('名称', text='名称')
        tree.heading('查询', text='查询内容')
        tree.heading('创建时间', text='创建时间')
        
        tree.column('名称', width=150)
        tree.column('查询', width=300)
        tree.column('创建时间', width=150)
        
        # 滚动条
        scrollbar = ttk.Scrollbar(frame, orient="vertical", command=tree.yview)
        tree.configure(yscrollcommand=scrollbar.set)
        
        tree.pack(side="left", fill="both", expand=True)
        scrollbar.pack(side="right", fill="y")
        
        # 填充书签
        def refresh_bookmarks():
            tree.delete(*tree.get_children())
            for bookmark in self.query_bookmarks:
                query_preview = bookmark['query'].replace('\n', ' ').strip()
                if len(query_preview) > 50:
                    query_preview = query_preview[:47] + "..."
                tree.insert('', 'end', values=(bookmark['name'], query_preview, bookmark['time']))
        
        refresh_bookmarks()
        
        # 按钮框架
        button_frame = ttk.Frame(frame)
        button_frame.pack(fill="x", pady=(10, 0))
        
        def add_bookmark():
            current_query = self.sql_editor.get(1.0, tk.END).strip()
            if not current_query:
                messagebox.showwarning("警告", "没有要保存的查询")
                return
            
            # 弹出对话框获取书签名称
            name = tk.simpledialog.askstring("新建书签", "请输入书签名称:")
            if name:
                from datetime import datetime
                bookmark = {
                    'name': name,
                    'query': current_query,
                    'time': datetime.now().strftime("%Y-%m-%d %H:%M")
                }
                self.query_bookmarks.append(bookmark)
                refresh_bookmarks()
                self.status_label.config(text=f"书签 '{name}' 已保存")
        
        def use_bookmark():
            selection = tree.selection()
            if selection:
                item = tree.item(selection[0])
                bookmark_name = item['values'][0]
                # 找到对应的书签
                for bookmark in self.query_bookmarks:
                    if bookmark['name'] == bookmark_name:
                        self.sql_editor.delete(1.0, tk.END)
                        self.sql_editor.insert(1.0, bookmark['query'])
                        bookmark_window.destroy()
                        self.status_label.config(text=f"书签 '{bookmark_name}' 已加载")
                        break
        
        def delete_bookmark():
            selection = tree.selection()
            if selection:
                item = tree.item(selection[0])
                bookmark_name = item['values'][0]
                if messagebox.askyesno("确认", f"确定要删除书签 '{bookmark_name}' 吗？"):
                    self.query_bookmarks = [b for b in self.query_bookmarks if b['name'] != bookmark_name]
                    refresh_bookmarks()
                    self.status_label.config(text=f"书签 '{bookmark_name}' 已删除")
        
        ttk.Button(button_frame, text="添加当前查询", command=add_bookmark).pack(side="left", padx=(0, 5))
        ttk.Button(button_frame, text="使用选中", command=use_bookmark).pack(side="left", padx=(0, 5))
        ttk.Button(button_frame, text="删除", command=delete_bookmark).pack(side="left", padx=(0, 5))
        ttk.Button(button_frame, text="关闭", command=bookmark_window.destroy).pack(side="right")
        
        # 双击使用
        tree.bind('<Double-1>', lambda e: use_bookmark())
    
    def history_previous(self):
        """上一条历史记录"""
        if self.query_history and self.history_index > 0:
            self.history_index -= 1
            self.sql_editor.delete(1.0, tk.END)
            self.sql_editor.insert(1.0, self.query_history[self.history_index])
            self.status_label.config(text=f"历史记录 {self.history_index + 1}/{len(self.query_history)}")
    
    def history_next(self):
        """下一条历史记录"""
        if self.query_history and self.history_index < len(self.query_history) - 1:
            self.history_index += 1
            self.sql_editor.delete(1.0, tk.END)
            self.sql_editor.insert(1.0, self.query_history[self.history_index])
            self.status_label.config(text=f"历史记录 {self.history_index + 1}/{len(self.query_history)}")
    
    def refresh_database(self):
        """刷新数据库"""
        self.db_explorer.refresh()
        self.status_label.config(text="数据库已刷新")
    
    def show_execution_plan(self):
        """显示执行计划"""
        sql = self.sql_editor.get(1.0, tk.END).strip()
        if not sql:
            messagebox.showwarning("提示", "请输入SQL语句")
            return
        
        try:
            # 生成执行计划
            tokens = self.lexical_analyzer.analyze(sql)
            ast = self.syntax_analyzer.parse(tokens)
            logical_plan = self.logical_plan_generator.generate_plan(ast)
            physical_plan = self.physical_plan_optimizer.optimize(logical_plan, self.storage_adapter)
            
            # 显示执行计划
            plan_window = tk.Toplevel(self.root)
            plan_window.title("执行计划")
            plan_window.geometry("600x400")
            
            plan_text = scrolledtext.ScrolledText(plan_window, font=("Consolas", 10))
            plan_text.pack(fill="both", expand=True, padx=10, pady=10)
            
            plan_text.insert(1.0, f"逻辑计划:\n{logical_plan}\n\n物理计划:\n{physical_plan}")
            plan_text.config(state="disabled")
            
        except Exception as e:
            messagebox.showerror("错误", f"生成执行计划失败: {e}")
    
    def setup_theme(self):
        """设置主题和样式"""
        try:
            # 创建样式
            style = ttk.Style()
            
            # 设置主题
            style.theme_use('clam')  # 使用现代主题
            
            # 自定义样式
            style.configure('Title.TLabel', font=('Arial', 12, 'bold'))
            style.configure('Status.TLabel', font=('Arial', 9))
            style.configure('Header.TLabel', font=('Arial', 10, 'bold'))
            
            # 自定义按钮样式
            style.configure('Action.TButton', font=('Arial', 9, 'bold'))
            style.map('Action.TButton',
                     background=[('active', '#0078d4'),
                               ('pressed', '#005a9e')])
            
            # 自定义树形视图样式
            style.configure('Custom.Treeview',
                          background='#ffffff',
                          foreground='#000000',
                          fieldbackground='#ffffff',
                          font=('Arial', 9))
            style.configure('Custom.Treeview.Heading',
                          background='#f0f0f0',
                          foreground='#000000',
                          font=('Arial', 9, 'bold'))
            
            # 设置窗口背景色
            self.root.configure(bg='#f5f5f5')
            
        except Exception as e:
            print(f"主题设置失败: {e}")
    
    def show_sql_help(self):
        """显示SQL帮助"""
        help_window = tk.Toplevel(self.root)
        help_window.title("SQL语法帮助")
        help_window.geometry("500x400")
        
        help_text = scrolledtext.ScrolledText(help_window, font=("Consolas", 10))
        help_text.pack(fill="both", expand=True, padx=10, pady=10)
        
        help_content = """SQL语法帮助

基本查询:
SELECT column1, column2 FROM table_name;
SELECT * FROM table_name WHERE condition;

插入数据:
INSERT INTO table_name (col1, col2) VALUES (val1, val2);

更新数据:
UPDATE table_name SET col1 = val1 WHERE condition;

删除数据:
DELETE FROM table_name WHERE condition;

创建表:
CREATE TABLE table_name (
    id INT PRIMARY KEY,
    name VARCHAR(50),
    age INT
);

删除表:
DROP TABLE table_name;

常用函数:
COUNT(*), MAX(column), MIN(column), AVG(column)

排序和分组:
ORDER BY column ASC/DESC
GROUP BY column
HAVING condition

限制结果:
LIMIT number
"""
        
        help_text.insert(1.0, help_content)
        help_text.config(state="disabled")
    
    def list_databases(self):
        """列出所有数据库"""
        sql = "LIST DATABASES;"
        self.sql_editor.delete(1.0, tk.END)
        self.sql_editor.insert(1.0, sql)
        self.execute_query()
    
    def create_database_dialog(self):
        """显示创建数据库对话框"""
        db_name = simpledialog.askstring("创建数据库", "请输入新数据库名称:")
        if db_name:
            # 验证数据库名称
            if not db_name.replace('_', '').replace('-', '').isalnum():
                messagebox.showerror("错误", "数据库名称只能包含字母、数字、下划线和连字符")
                return
            
            sql = f"CREATE DATABASE {db_name};"
            self.sql_editor.delete(1.0, tk.END)
            self.sql_editor.insert(1.0, sql)
            self.execute_query()
    
    def drop_database_dialog(self):
        """显示删除数据库对话框"""
        try:
            # 获取数据库列表
            databases = self.storage_adapter.db_adapter.list_databases()
            if not databases:
                messagebox.showinfo("信息", "没有可删除的数据库")
                return
            
            # 创建选择对话框
            dialog = tk.Toplevel(self.root)
            dialog.title("删除数据库")
            dialog.geometry("300x200")
            dialog.transient(self.root)
            dialog.grab_set()
            
            # 居中显示
            dialog.update_idletasks()
            x = (dialog.winfo_screenwidth() // 2) - (dialog.winfo_width() // 2)
            y = (dialog.winfo_screenheight() // 2) - (dialog.winfo_height() // 2)
            dialog.geometry(f"+{x}+{y}")
            
            ttk.Label(dialog, text="选择要删除的数据库:", font=("Arial", 10, "bold")).pack(pady=10)
            
            # 数据库列表
            db_var = tk.StringVar()
            db_combo = ttk.Combobox(dialog, textvariable=db_var, values=databases, state="readonly")
            db_combo.pack(pady=5, padx=20, fill="x")
            
            # 警告信息
            warning_label = ttk.Label(dialog, text="⚠️ 警告：删除数据库将永久删除其中的所有数据！", 
                                    foreground="red", font=("Arial", 9))
            warning_label.pack(pady=10)
            
            result = {"confirmed": False, "db_name": None}
            
            def on_delete():
                if not db_var.get():
                    messagebox.showwarning("警告", "请选择要删除的数据库")
                    return
                
                if db_var.get() == self.database_name:
                    messagebox.showerror("错误", "不能删除当前正在使用的数据库")
                    return
                
                if messagebox.askyesno("确认删除", f"确定要删除数据库 '{db_var.get()}' 吗？\n\n此操作不可撤销！"):
                    result["confirmed"] = True
                    result["db_name"] = db_var.get()
                    dialog.destroy()
            
            def on_cancel():
                dialog.destroy()
            
            # 按钮
            button_frame = ttk.Frame(dialog)
            button_frame.pack(pady=15)
            
            ttk.Button(button_frame, text="删除", command=on_delete, style="Action.TButton").pack(side="left", padx=5)
            ttk.Button(button_frame, text="取消", command=on_cancel).pack(side="left", padx=5)
            
            dialog.wait_window()
            
            if result["confirmed"]:
                sql = f"DROP DATABASE {result['db_name']};"
                self.sql_editor.delete(1.0, tk.END)
                self.sql_editor.insert(1.0, sql)
                self.execute_query()
                
        except Exception as e:
            messagebox.showerror("错误", f"获取数据库列表失败: {e}")
    
    def use_database_dialog(self):
        """显示切换数据库对话框"""
        try:
            # 获取数据库列表
            databases = self.storage_adapter.db_adapter.list_databases()
            if not databases:
                messagebox.showinfo("信息", "没有可切换的数据库")
                return
            
            # 过滤掉当前数据库
            available_databases = [db for db in databases if db != self.database_name]
            if not available_databases:
                messagebox.showinfo("信息", "没有其他数据库可切换")
                return
            
            # 创建选择对话框
            dialog = tk.Toplevel(self.root)
            dialog.title("切换数据库")
            dialog.geometry("300x150")
            dialog.transient(self.root)
            dialog.grab_set()
            
            # 居中显示
            dialog.update_idletasks()
            x = (dialog.winfo_screenwidth() // 2) - (dialog.winfo_width() // 2)
            y = (dialog.winfo_screenheight() // 2) - (dialog.winfo_height() // 2)
            dialog.geometry(f"+{x}+{y}")
            
            ttk.Label(dialog, text="选择要切换到的数据库:", font=("Arial", 10, "bold")).pack(pady=10)
            
            # 数据库列表
            db_var = tk.StringVar()
            db_combo = ttk.Combobox(dialog, textvariable=db_var, values=available_databases, state="readonly")
            db_combo.pack(pady=5, padx=20, fill="x")
            
            if available_databases:
                db_combo.set(available_databases[0])  # 默认选择第一个
            
            result = {"confirmed": False, "db_name": None}
            
            def on_switch():
                if not db_var.get():
                    messagebox.showwarning("警告", "请选择要切换到的数据库")
                    return
                
                result["confirmed"] = True
                result["db_name"] = db_var.get()
                dialog.destroy()
            
            def on_cancel():
                dialog.destroy()
            
            # 按钮
            button_frame = ttk.Frame(dialog)
            button_frame.pack(pady=15)
            
            ttk.Button(button_frame, text="切换", command=on_switch, style="Action.TButton").pack(side="left", padx=5)
            ttk.Button(button_frame, text="取消", command=on_cancel).pack(side="left", padx=5)
            
            dialog.wait_window()
            
            if result["confirmed"]:
                # 直接调用DatabaseExplorer的switch_database方法
                self.db_explorer.switch_database(result["db_name"])
                
        except Exception as e:
            messagebox.showerror("错误", f"获取数据库列表失败: {e}")
    
    def show_about(self):
        """显示关于信息"""
        messagebox.showinfo("关于", 
                          "数据库管理工具 v1.0\n\n"
                          "基于Python tkinter开发的图形化数据库客户端\n"
                          "支持SQL查询、表浏览、数据编辑等功能\n\n"
                          "© 2024 Database System Project")
    
    def run(self):
        """启动应用"""
        try:
            # 设置窗口关闭事件处理
            self.root.protocol("WM_DELETE_WINDOW", self._on_closing)
            self.root.mainloop()
        finally:
            # 确保数据库被正确关闭
            self._cleanup_database_connections()
    
    def _on_closing(self):
        """窗口关闭事件处理"""
        try:
            # 确保数据库被正确关闭
            self._cleanup_database_connections()
        finally:
            self.root.destroy()
    
    def _cleanup_database_connections(self):
        """清理数据库连接"""
        try:
            if hasattr(self, 'storage_adapter') and self.storage_adapter:
                # 获取数据库服务器
                db_server = self.storage_adapter.db_adapter.database_server
                if db_server:
                    # 获取system数据库并关闭
                    system_db = db_server.database_manager.get_database("system")
                    if system_db:
                        print("正在关闭system数据库...")
                        system_db.close()
                    
                    # 关闭数据库管理器中的所有数据库
                    for db_name, db_instance in db_server.database_manager.databases.items():
                        if db_instance and db_instance != system_db:
                            print(f"正在关闭数据库: {db_name}")
                            db_instance.close()
                    
                    print("数据库连接清理完成")
        except Exception as e:
            print(f"清理数据库连接时出错: {e}")

    
    def show_user_info(self):
        """显示用户信息"""
        if not self.is_authenticated:
            messagebox.showerror("错误", "用户未认证")
            return
        
        info_window = tk.Toplevel(self.root)
        info_window.title("用户信息")
        info_window.geometry("400x300")
        info_window.resizable(False, False)
        info_window.transient(self.root)
        info_window.grab_set()
        
        # 居中显示
        info_window.update_idletasks()
        x = (info_window.winfo_screenwidth() // 2) - (info_window.winfo_width() // 2)
        y = (info_window.winfo_screenheight() // 2) - (info_window.winfo_height() // 2)
        info_window.geometry(f"+{x}+{y}")
        
        # 创建内容
        main_frame = ttk.Frame(info_window, padding="20")
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 标题
        title_label = ttk.Label(main_frame, text="用户信息", font=("Arial", 16, "bold"))
        title_label.pack(pady=(0, 20))
        
        # 信息显示
        info_frame = ttk.Frame(main_frame)
        info_frame.pack(fill=tk.BOTH, expand=True)
        
        # 用户名
        ttk.Label(info_frame, text="用户名:", font=("Arial", 10, "bold")).grid(row=0, column=0, sticky=tk.W, pady=5)
        ttk.Label(info_frame, text=self.current_user).grid(row=0, column=1, sticky=tk.W, padx=(10, 0), pady=5)
        
        # 认证状态
        ttk.Label(info_frame, text="认证状态:", font=("Arial", 10, "bold")).grid(row=1, column=0, sticky=tk.W, pady=5)
        status_text = "已认证" if self.is_authenticated else "未认证"
        ttk.Label(info_frame, text=status_text, foreground="green" if self.is_authenticated else "red").grid(row=1, column=1, sticky=tk.W, padx=(10, 0), pady=5)
        
        # 当前数据库
        ttk.Label(info_frame, text="当前数据库:", font=("Arial", 10, "bold")).grid(row=2, column=0, sticky=tk.W, pady=5)
        ttk.Label(info_frame, text=self.database_name).grid(row=2, column=1, sticky=tk.W, padx=(10, 0), pady=5)
        
        # 数据根目录
        ttk.Label(info_frame, text="数据目录:", font=("Arial", 10, "bold")).grid(row=3, column=0, sticky=tk.W, pady=5)
        ttk.Label(info_frame, text=self.data_root).grid(row=3, column=1, sticky=tk.W, padx=(10, 0), pady=5)
        
        # 登录时间（如果有的话）
        try:
            login_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            ttk.Label(info_frame, text="会话时间:", font=("Arial", 10, "bold")).grid(row=4, column=0, sticky=tk.W, pady=5)
            ttk.Label(info_frame, text=login_time).grid(row=4, column=1, sticky=tk.W, padx=(10, 0), pady=5)
        except:
            pass
        
        # 关闭按钮
        button_frame = ttk.Frame(main_frame)
        button_frame.pack(pady=(20, 0))
        
        ttk.Button(button_frame, text="关闭", command=info_window.destroy).pack()
    
    def logout(self):
        """用户注销"""
        if not self.is_authenticated:
            messagebox.showinfo("提示", "用户未登录")
            return
        
        if messagebox.askyesno("确认注销", f"确定要注销用户 {self.current_user} 吗？"):
            try:
                # 调用存储适配器的注销方法
                self.storage_adapter.logout()
                
                # 重置认证状态
                self.is_authenticated = False
                self.current_user = None
                
                # 关闭主窗口
                self.root.destroy()
                
                messagebox.showinfo("注销成功", "用户已注销，程序将退出")
                
            except Exception as e:
                messagebox.showerror("注销失败", f"注销过程中发生错误: {e}")


def main():
    """主函数"""
    import argparse
    
    parser = argparse.ArgumentParser(description="数据库图形界面客户端")
    parser.add_argument("--data-root", default="database", help="数据根目录")
    parser.add_argument("--database", default="demo_db", help="数据库名称")
    
    args = parser.parse_args()
    
    try:
        app = DatabaseGUI(data_root=args.data_root, database_name=args.database)
        app.run()
    except Exception as e:
        messagebox.showerror("启动错误", f"应用启动失败: {e}")
        sys.exit(1)


if __name__ == "__main__":
    main()
